#ifndef __ICESERVER_H__
#define __ICESERVER_H__

#include <iostream>
#include <string>
#include <Ice/Ice.h>
#include "plog.h"


template< class T >
class CICEServer{
private:
	bool m_EnableFlag;

	string m_proxyname;
	string m_connstr;
	string m_servantname;


	Ice::CommunicatorPtr ic;
	Ice::ObjectAdapterPtr adapter ;
	T * m_ice_srv_p;

	string m_ice_err;
	ERROR_RECORDER m_err_recorder;
public:
	CICEServer( string, string, string );
	virtual ~CICEServer();
	
	virtual bool Initialize();
	virtual void Uninitialize();
	virtual bool Run();
	virtual string GetErrInfo();
};

/** 
 * @brief 
 * 
 * @param proxyname
 * @param connstr
 * @param servantname
 */
template<class T>
CICEServer<T>::CICEServer( string proxyname , string connstr , string servantname ){
	m_proxyname = proxyname;
	m_connstr = connstr;
	m_servantname = servantname;
	m_ice_srv_p = NULL;
}

/** 
 * @brief 
 */
template<class T>
CICEServer<T>::~CICEServer(){
	Uninitialize();
}

/** 
 * @brief 
 * 
 * @return 
 */
template<class T>
bool CICEServer<T>::Initialize( ){

	int argc = 0;
	char ** argv = NULL;

	try {
		ic = Ice::initialize(argc, argv);
		
		adapter = ic->createObjectAdapterWithEndpoints( m_proxyname , m_connstr );

		m_ice_srv_p = new T;
		if( !m_ice_srv_p->Initialize() ){
			PLOG( "Ice Server initialize failed" );
			return false;
		}

		Ice::ObjectPtr object = m_ice_srv_p;

		adapter->add(object, ic->stringToIdentity( m_servantname ) );

	} catch (const Ice::Exception& ex) {
		m_ice_err = ex.ice_name();
		PLOG( m_ice_err );
		return false;

	} catch (...) {
		PLOG_CATCH_UNKNOWN();	
		return false;
	}

	return true;
}

/** 
 * @brief 
 */
template<class T>
void CICEServer<T>::Uninitialize(){

	if( m_ice_srv_p ){
		delete m_ice_srv_p ;
		m_ice_srv_p = NULL;
	}

	if (ic) {
		try {
			ic->destroy();
		}catch(const Ice::Exception& ex) {
			m_ice_err = ex.ice_name();
			PLOG( m_ice_err );
		}catch( ... ){
			PLOG_CATCH_UNKNOWN();	
			return;
		}
	}
	return;
}

/** 
 * @brief 
 */
template<class T>
bool CICEServer<T>::Run(){
	try {
		adapter->activate();

		ic->waitForShutdown();

	}catch( const Ice::Exception& ex){
		m_ice_err = ex.ice_name();
		PLOG( m_ice_err );
		return false;
	}catch( ... ){
		PLOG_CATCH_UNKNOWN();
		return false;
	}

	return true;
}

/** 
 * @brief 
 */
template< class T >
string CICEServer<T>::GetErrInfo(){
	return m_ice_err;
}

#endif
